(function($) {
	$.m = {
		version : "1.0",
		timeFormat : "yyyy-MM-dd HH:mm:ss",
		dateFormat : "yyyy-MM-dd",
		test : "test"
	};

	String.prototype.replaceAll = function(source, replaceWith, ignoreCase) {  
	    if (!RegExp.prototype.isPrototypeOf(source)) {  
	        return this.replace(new RegExp(source, (ignoreCase ? "gi": "g")), replaceWith);  
	    } else {  
	        return this.replace(source, replaceWith);  
	    }  
	};

	String.prototype.endsWith = function(str){
		if(str==null || str=="" || this.length == 0 ||str.length > this.length){
			return false;
		}
		if(this.substring(this.length - str.length)){
			return true;
		}else{
			return false;
		}
		return true;
	};

	String.prototype.startsWith = function(str){
		if(str == null || str== "" || this.length== 0 || str.length > this.length){
			return false;
		}
		if(this.substr(0,str.length) == str){
			return true;
		}else{
			return false;
		}
		return true;
	};


    $.fn.serializeJSON = function(){
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name]) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };

    $.m.scrollTo = function (ele, distance) {
        mUtil.scrollTo(ele, distance);
    };

    $.m.getParam = function(url, name) {
		var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(url);
		return results == null ? null : results[1];
	};
	
	$.m.groupBy = function(array, keyFunction){
		var map = {};
		$.each(array, function(i, e){
			map[keyFunction(e)] = e;
		})
		return map;
	}

    $.m.alert = function(options){
        var alertOptions = {};
        var defaultAlertOptions = {
            title : $.i18n.alert,
            confirmButtonText: $.i18n.ok,
            cancelButtonText: $.i18n.cancel,
        };
        if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
            alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
        } else {
            alertOptions = $.extend(true, defaultAlertOptions, {
                title: arguments[0],
				text: typeof arguments[1] !== 'undefined' ? arguments[1] : null,
				type: typeof arguments[2] !== 'undefined' ? arguments[2] : null
            });
        }
        var swalOptions = $.extend({}, alertOptions);
        if (swalOptions.message) {
            swalOptions.text = swalOptions.message;
            delete swalOptions.message;
        }
        delete swalOptions.callback;
        var s = swal(swalOptions);

        if (alertOptions.callback) {
			s.then(function (result) {
				alertOptions.callback.call(this, result);
			});
        }
		return s;
    };

    $.m.success = function (options) {
        var alertOptions = {
		};
        var defaultAlertOptions = {
            title : $.i18n.alert,
            type: 'success',
        };
        if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
            alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
        } else {
            alertOptions = $.extend(true, defaultAlertOptions, {
                title: arguments[0],
                text: typeof arguments[1] !== 'undefined' ? arguments[1] : null,
            });
        }
        return $.m.alert(alertOptions);
    };

    $.m.error = function (options) {
        var alertOptions = {
        };
        var defaultAlertOptions = {
            title : $.i18n.alert,
            type: 'error',
        };
        if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
            alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
        } else {
            alertOptions = $.extend(true, defaultAlertOptions, {
                title: arguments[0],
                text: typeof arguments[1] !== 'undefined' ? arguments[1] : null,
            });
        }
        return $.m.alert(alertOptions);
    };

    $.m.confirm = function (options) {
        var alertOptions = {};
        var defaultAlertOptions = {
            title: $.i18n.confirm,
            type: 'question',
            showCancelButton: true,
            confirmButtonText: $.i18n.ok,
            cancelButtonText: $.i18n.cancel,
        };
        if (typeof arguments[0] === 'object' && arguments[0].constructor === {}.constructor) {
            alertOptions = $.extend(true, defaultAlertOptions, arguments[0]);
        } else {
            alertOptions = $.extend(true, defaultAlertOptions, {
                title: arguments[0],
                text: typeof arguments[1] !== 'undefined' ? arguments[1] : null,
                type: typeof arguments[2] !== 'undefined' ? arguments[2] : null
            });
        }

        var swalOptions = $.extend({}, alertOptions);
        if (swalOptions.message) {
            swalOptions.text = swalOptions.message;
            delete swalOptions.message;
        }
        delete swalOptions.callback;
        delete swalOptions.ok;
        delete swalOptions.cancel;
        var s = swal(swalOptions);

        if (alertOptions.callback) {
            s.then(function (result) {
                alertOptions.callback.call(this, result);
            });
        } else if(alertOptions.ok || alertOptions.cancel){
            s.then(function (result) {
                if (result.value) {
                    if (alertOptions.ok) alertOptions.ok.call(this);
                } else if (result.dismiss === 'cancel') {
                    // result.dismiss can be 'cancel', 'overlay',
                    // 'close', and 'timer'
                    if (alertOptions.cancel) alertOptions.cancel.call(this);
                }
            });
        }
        return s;
    };

    $.m.block = function(options){
        if(typeof options=='string'){
            options = {
                boxed : true,
                message: options
            }
        }; // By ZhangPei
        options = $.extend(true, {}, options);

        if (options.target) { // element blocking
            var el = $(options.target);
            mApp.block(el, options);
        } else {
            mApp.blockPage(options);
		}
	};

    $.m.unblock = function(target){
        mApp.unblock(target);
    };

    $.m.blockPage = function(options) {
        if(typeof options=='string'){
            options = {
                boxed : true,
                message: options
            }
        }; // By ZhangPei
        return mApp.block('body', options);
    };

    $.m.unblockPage = function() {
        return mApp.unblock('body');
    };

	$.m.ajaxAction = function(options){
		$.ajax($.extend(true, {
			cache: false,
            traditional: true,
			type: 'post',
            dataType:'json',
            headers: {
            	ajax: true
            },
            success: function(data) {
                if(data.success){
                	if(options.successCallback){
                    	options.successCallback(data)
                	}
                } else {
                	if(!options.errorCallback){
                		$.m.error(data.message);
                	} else {
                    	options.errorCallback(data)
                	}
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
            	$.m.error($.i18n.unexpectedServerError + ", status["+textStatus+"], code["+XMLHttpRequest.status+"], detail["+errorThrown+"]");
            }
		}, options));
	};
	
	$.m.ajaxSubmit = function($form, options){
		$.ajax($.extend(true, {
			cache: false,
			type: 'post',
            dataType:'json',
            headers: {
            	ajax: true
            },
            data: $form.serialize(),
            success: function(data) {
                if(data.success){
                	if(options.successCallback){
                    	options.successCallback(data)
                	}
                } else {
                	if(!options.errorCallback){
                        $.m.error(data.message);
                	} else {
                    	options.errorCallback(data)
                	}
                }
            },
            error: function (XMLHttpRequest, textStatus, errorThrown) {
            	$.m.error($.i18n.unexpectedServerError + ", status["+textStatus+"], code["+XMLHttpRequest.status+"], detail["+errorThrown+"]");
            }
		}, options));
	};
	
	$.m.initPaginator = function(options){
		if(!$.fn.bootstrapPaginator){
			alert("Miss plugin [bootstrapPaginator]");
			return;
		}
   		var searchDataCallback = function(data, options){
   			var serverPageData = data.data;
   			if(serverPageData.totalElements<=0){
				options.dataContainer.html(options.onRenderEmptyData(data, options));
				return;
			}
   			options.onRenderPaginator(data, options);
   			options.dataContainer.html(options.onRenderData(data, options));
   		};
   		
   		var $container = options.paginator;
   		$container.html('<nav><ul></ul></nav>');
   		var $paginator = $container.find("ul");
   		options = $.extend(true,{
   			initPage: 1,
   			pageSize: 10,
   			numberOfPages:5,
   			onRenderEmptyData: function(data, options){
   				return '<div class="col-md-12 col-sm-12"><div class="alert alert-info center">'+$.i18n.zeroRecords+' </div></div>';
   			},
   			onRenderPaginator: function(data, options){
   				var serverPageData = data.data;
   				var currentPage = serverPageData.number + 1;
   				var totalPages = serverPageData.totalPages;
   				var isFirst = currentPage==1;
   				var isLast = currentPage==totalPages;
   				if(serverPageData.totalElements<=0){
   					// todo display no data
   					$container.hide();
   					options.onRenderEmptyData(data, options);
   					return;
   				}
   				$paginator.bootstrapPaginator({
   					bootstrapMajorVersion: 3,
       				numberOfPages: options.numberOfPages,
    	            currentPage: currentPage,
    	            totalPages: serverPageData.totalPages,
    	            shouldShowPage:function(type, page, current){
    	                switch(type)
    	                {
    	                    case "first":
    	                    case "last":
    	                        return false;
    	                    default:
    	                        return true;
    	                }
    	            },
    	            itemContainerClass: function (type, page, current) {
    	            	if(((type=='first' || type=='prev')&& isFirst) || ((type=='last' || type=='next') && isLast)){
    	            		return "disabled";
    	            	}
    	                return (page === current) ? "active" : "pointer-cursor";
    	            },
    	            onPageClicked:function(event, originalEvent, type, page){
    	            },
    				onPageChanged:function(event, oldPage, newPage){
    					options.onSearchData(newPage, options, searchDataCallback);
    	            }
   				});
   			}
   		}, options);
   		
   		options.onSearchData(options.initPage, options, searchDataCallback);
   	}
	
})(jQuery);